#!/usr/bin/env python3 
# -*- coding: utf-8 -*- 
###----------1、文件说明----------### 
''' 
* 说明：conan安装配置文件
* 时间：
* 文件：
* 作者：Smile
* 版本：0.1
* 模板版本: 0.2
 - 0.2 添加 source validate finalize等函数，修改获取系统信息功能的代码存放位置
* 库版本: 
 - conan: 2.14.0
* 备注： 
'''
import os,sys
from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps
from conan.tools.system import package_manager
from pprint import pprint
import platform
import importlib
from datetime import datetime
import time
import shutil
import tempfile

def getClassValue(sclass):
    '''
    获取类的子属性
    版本: 0.1
    :param sclass:
    :return:
    '''
    from types import FunctionType, BuiltinFunctionType, MethodType

    print("Get Class ", type(sclass))
    for i in dir(sclass):
        tmp = getattr(sclass, i)
        if isinstance(tmp, FunctionType) or isinstance(tmp, BuiltinFunctionType):
            print(i, "\t", type(tmp), "Function")
        else:
            print(i, "\t", type(tmp), tmp)

manager_mapping = {"Apt": ["Linux", "ubuntu", "kylin", "debian", "raspbian", "linuxmint", 'astra', 'elbrus', 'altlinux', 'pop'],
                    "Apk": ["alpine"],
                    "Yum": ["pidora", "scientific", "xenserver", "amazon", "oracle", "amzn",
                            "almalinux", "rocky"],
                    "Dnf": ["fedora", "rhel", "centos", "mageia", "nobara"],
                    "Brew": ["Darwin"],
                    "PacMan": ["arch", "manjaro", "msys2", "endeavouros"],
                    "Chocolatey": ["Windows"],
                    "Zypper": ["opensuse", "sles"],
                    "Pkg": ["freebsd"],
                    "Pkgutil": ["Solaris"]}

class SoftConfigRecipe(ConanFile):
    name = "softinstall"
    version = "0.1"
    installversion = "v1.23.8"
    package_type = "build-scripts"

    # 个人信息
    license = "MIT"
    author = "<OSmile> <whghcyx@outlook.com>"
    url = "https://whg555.github.io"
    description = "readme description"
    topics = ("<Put some tag here>", "<here>", "<and here>")

    # 二进制配置
    settings = "os", "compiler", "build_type", "arch"

    # 针对特定系统的安装包
    packages = {
        "ubuntu" :  {
            "default" : ["gcc"], # 当前系统通用的包
            "20" : ["gcc"], # 特定版本号的包
        },
        "kylin" : {
            "default" : ["gcc"], # 当前系统通用的包
            "v10" :  ["gcc"], # 当前系统通用的包
        },
        "default" : {
            "default" : ["gcc"]
        }
    }

    def init(self):
        '''
        <1>conan create .
        <3>conan create .
        <1>conan install .
        :return:
        '''
        # 判断函数运行的时间
        self.starttime = datetime.now()
        # 判断函数调用顺序的变量
        if not hasattr(self, "runfunnum"):
            self.runfunnum = 0
        print("\033[43;34mOSmile-->", "init", "<" + str(datetime.now() - self.starttime) +  ">", "\033[0m")
        # 更新当前函数调用的
        self.runfunnum += 1
        print("\033[43;34mOSmile-->", self.runfunnum, "\033[0m")
        # 创建缓存目录
        # self.tmppath = tempfile.mkdtemp()
        self.tmppath = os.path.join(os.path.expanduser("~"), "conantmp")
        os.makedirs(self.tmppath, exist_ok=True)

        # 获取系统版本信息
        os_name = platform.system()
        self.os_name = self.os_version = self.os_base = ""
        self.os_base = os_name
        if os_name in ["Linux", "FreeBSD"]:
            import distro
            self.os_name = distro.id() or os_name
            self.os_version = distro.version(best=True).split(".")[0]
        # elif os_name == "Windows" and self.settings.get_safe("os.subsystem") == "msys2":
        elif os_name == "Windows":
            self.os_name = "msys2"
            self.os_version = ""

    def export_sources(self):
        '''
        <2>conan create .
        :return:
        '''
        print("\033[43;34mOSmile-->", "export_sources", "<" + str(datetime.now() - self.starttime) +  ">", "\033[0m")

    def config_options(self):
        '''
        针对系统，对配置命令做一些修改
        <4>conan create .
        <2>conan install .
        <test><1>conan create .
        '''

        print("\033[43;34mOSmile-->", "config_options", "<" + str(datetime.now() - self.starttime) + ">", "\033[0m")
        # pprint(self.settings.values_list)
        # pprint(self.serialize())
        # print("self.conf", self.conf)

        print("System   -->", self.os_base) # Windows Linux
        print("OSSystem -->", self.os_name) # msys2 ubuntu
        print("Version  -->", self.os_version) # 20
        print("TmpPath  -->", self.tmppath)
        print("ARCH     -->", self.settings.get_safe("arch")) # x86_64 armv8
        print("cwd      -->", os.getcwd())

    def configure(self):
        '''
        <5>conan create .
        <3>conan install .
        <test><2>conan create .
        '''
        print("\033[43;34mOSmile-->", "configure", "<" + str(datetime.now() - self.starttime) + ">", "\033[0m")
        if self.os_name == "kylin":
            self.conf.define("tools.system.package_manager:tool", "apt-get")
        self.conf.define("tools.system.package_manager:mode", "install")
        self.conf.define("tools.system.package_manager:sudo", True)



    def validate_build(self):
        '''
        <6>conan create .
        <4>conan install .
        :return:
        '''
        print("\033[43;34mOSmile-->", "validate_build", "<" + str(datetime.now() - self.starttime) +  ">", "\033[0m")

    def validate(self):
        '''
        <7>conan create .
        <5>conan install .

        :return:
        '''
        print("\033[43;34mOSmile-->", "validate", "<" + str(datetime.now() - self.starttime) + ">", "\033[0m")

    def package_id(self):
        '''
        <8>conan create .
        <6>conan install .
        :return:
        '''
        print("\033[43;34mOSmile-->", "package_id", "<" + str(datetime.now() - self.starttime) +  ">", "\033[0m")

    def compatibility(self):
        ''' '''
        print("\033[43;34mOSmile-->", "compatibility", "<" + str(datetime.now() - self.starttime) +  ">", "\033[0m")

    def layout(self):
        '''
        <9>conan create .
        <7>conan install .
        <test><3>conan create .
        '''
        print("\033[43;34mOSmile-->", "layout", "<" + str(datetime.now() - self.starttime) + ">", "\033[0m")
        cpuname = osname = ""
        if self.settings.get_safe("arch") == "x86_64":
            cpuname = "amd64"
        elif self.settings.get_safe("arch") == "armv8":
            cpuname = "arm64"

        if self.os_base == "Windows":
            self.filename = "gitea-" + self.installversion.replace("v", "") + "-windows-4.0-" + cpuname + ".exe"
        elif self.os_base == "Linux":
            self.filename = "gitea-" + self.installversion.replace("v", "") + "-linux-" + cpuname
        else:
            self.filename = "gitea-" + self.installversion.replace("v", "")
        url = "https://github.com/go-gitea/gitea/releases/download/" + self.installversion + "/" + self.filename
        self.localfilename = os.path.join(self.tmppath, self.filename)
        print("install  file", self.filename)
        print("download file", url)


        if not os.path.exists(self.localfilename):
            # self.run(f"wget {url}", ignore_errors=True)
            self.requestProxyDown(url, self.localfilename)

    def requestProxyDown(self, url, name="demo.wb", proxy={"http": "127.0.0.1:7890"}):
        '''代理下载 '''
        import requests
        from tqdm import tqdm

        proxy = {
            "http": "127.0.0.1:7890",
            "https": "127.0.0.1:7890",
        }

        r = requests.get(url, stream=True, proxies=proxy)
        total_size = int(r.headers.get('content-length', 0))  # 获取文件总大小
        # 打开文件并写入内容，同时显示进度条
        with open(name, "wb") as f, tqdm(
                desc=name,  # 进度条描述
                total=total_size,  # 总大小
                unit='B',  # 单位
                unit_scale=True,  # 自动选择合适的单位（如 KB、MB）
                unit_divisor=1024  # 单位换算基数
        ) as bar:
            for chunk in r.iter_content(chunk_size=8192):  # 每次读取 8KB
                if chunk:  # 过滤掉保持连接的新块
                    f.write(chunk)  # 写入文件
                    bar.update(len(chunk))  # 更新进度条

    def requestDownLarge(url, name="demo.wb"):
        '''下载大文件'''
        import requests
        r = requests.get(url, stream=True)

        with open(name, "wb") as f:
            for ch in r:
                f.write(ch)

    def system_requirements(self):
        '''
        安装需要的软件
        <10>conan create .
        <8>conan install .
        <test><4>conan create .
        '''
        print("\033[43;34mOSmile-->", "system_requirements", "<" + str(datetime.now() - self.starttime) + ">", "\033[0m")
        if platform.system() in ["Linux", "FreeBSD"]:
            # 获取编译工具
            for tool, distros in manager_mapping.items():
                if self.os_name in distros:
                    break
            # 查找需要安装的包
            os_name_key = self.os_name if (self.os_name in self.packages.keys()) else "default"
            os_version_key = self.os_version if (self.os_version in self.packages[os_name_key].keys()) else "default"
            softs = self.packages.get(os_name_key).get(os_version_key)
            print("安装软件包-->", softs)
            softtool = getattr(package_manager, tool)(self)
            softtool.install(softs, update=False, check=True)
        elif platform.system() == "Windows" and self.settings.get_safe("os.subsystem") == "msys2":
            os_name = "msys2"

    def source(self):
        '''
        <11>conan create .
        :return:
        '''
        print("\033[43;34mOSmile-->", "source", "<" + str(datetime.now() - self.starttime) + ">", "\033[0m")




    def build_id(self):
        '''
        <12>conan create .
        :return:
        '''
        print("\033[43;34mOSmile-->", "build_id", "<" + str(datetime.now() - self.starttime) +  ">", "\033[0m")

    def generate(self):
        '''
        配置已经安装的软件
        <13>conan create .
        <9>conan install .
        '''
        print("\033[43;34mOSmile-->", "generate", "<" + str(datetime.now() - self.starttime) + ">", "\033[0m")

        # 删除缓存目录
        # if os.path.exists(self.tmppath):
        #     shutil.rmtree(self.tmppath)

    def build(self):
        '''
        <14>conan create .
        '''
        print("\033[43;34mOSmile-->", "build", "<" + str(datetime.now() - self.starttime) + ">", "\033[0m")

    def imports(self):
        '''

        '''
        print("\033[43;34mOSmile-->", "imports", "<" + str(datetime.now() - self.starttime) + ">", "\033[0m")

    def package(self):
        '''
        <15>conan create .
        '''
        print("\033[43;34mOSmile-->", "package", "<" + str(datetime.now() - self.starttime) + ">", "\033[0m")

    def finalize(self):
        '''
        <16>conan create .
        :return:
        '''
        print("\033[43;34mOSmile-->", "finalize", "<" + str(datetime.now() - self.starttime) +  ">", "\033[0m")
        # 删除缓存目录
        if os.path.exists(self.tmppath):
            shutil.rmtree(self.tmppath)

    def package_info(self):
        '''
        <17>conan create .
        <test><5>conan create .
        '''
        print("\033[43;34mOSmile-->", "package_info", "<" + str(datetime.now() - self.starttime) + ">", "\033[0m")
